home *** CD-ROM | disk | FTP | other *** search
- /*
- * scan.c
- *
- * Scanner specific module of a scanner driver for scanning from
- * SGI image files. This driver supports greyscale and rgb
- * versions of the SGI image file.
- *
- * If you are writing a scanner driver, please refer to the
- * comments in the template version of scan.c for more
- * information about what is going on here. Also, look in
- * /usr/include/imp.h and the libimp(3) manual page for the
- * interface that this module uses to deal with SGI image files.
- *
- * Copyright 1992, 1993 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- #include <sys/types.h>
- #include <sys/times.h>
- #include <sys/param.h>
- #include <sys/prctl.h>
- #include <sys/wait.h>
-
- #include <stdio.h>
- #include <dslib.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <string.h>
- #include <bstring.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <invent.h>
- #include <unistd.h>
- #include <imp.h>
- #include <locale.h>
-
- #include <msgs/uxsgiimpr.h>
-
- #include <scanner.h>
- #include <scandrv.h>
-
- #include "scan.h"
- #include "main.h"
-
- /*
- * Stuff for converting from color images to greyscale
- */
- #define RINTLUM (77)
- #define GINTLUM (150)
- #define BINTLUM (29)
- #define ILUM(r,g,b) ((RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
- #define ILUM16(r,g,b) ((RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b)))
-
- /*
- * Stuff from converting from greyscale to monochrome
- */
- #define THRESH(val,thresh) ((val) > (thresh) ? 1 : 0)
- #define THRESHVAL 128
-
- /*
- * Scale a pixel from 2 bytes to 1 byte
- */
- #define SCALE(pixel) (((pixel * 255) / (imgMaxValue - imgMinValue)) & 0xff)
-
- /*
- * imgOffset and imgStride are global variables used in the conversion
- * functions. imgOffset is the number of pixels in each row to skip
- * while converting, and imgStride is the number of pixels in each row.
- *
- * The reason we do this is that the libimp interface gives us image
- * data a row at a time, and the scan interface requires us to crop
- * the scanned area. We do the cropping at the same time that we
- * convert the data to a format that fits into the scan interface spec
- * so that we only need to do one pass of conversion over each row.
- * This all gets done in the DoImgProc thread, which calls our convert
- * function for each row (see SetupScan below).
- */
- static int imgOffset, imgStride;
-
- /*
- * Temporary memory for holding rows being scaled down from 16 bits to
- * 8 bit.
- */
- static void *imgTempBuf = NULL;
-
- /*
- * These global variables get used by the function that scales 16 bit
- * per pixel data down to 8 bit pixel data.
- */
- static long imgMaxValue, imgMinValue;
-
- /*
- * Pointer to a function for getting rows of data from the image file.
- * We use this level of indirection to avoid having to do a
- * complicated if test in DoScan; instead, we do all the testing we
- * need in SetupScan and set imgGetRows appropriately.
- */
- static int (*imgGetRows)(IMPImage *img, short y, short z,
- void *buf, int nrows);
-
- /*
- * static int
- * HowManyBits(unsigned short maxVal)
- *
- * Description:
- * Figure out how many bits need to be used to represent maxVal
- *
- * Parameters:
- * maxVal
- *
- * Returns:
- * The number of bits necessary to represent maxVal
- */
-
- static int
- HowManyBits(unsigned short maxVal)
- {
- int i;
-
- /*
- * You still need at least a bit to represent all 0's.
- */
- if (!maxVal) {
- return 1;
- }
-
- i = 0;
- while (maxVal) {
- i++;
- maxVal >>= 1;
- }
- return i;
- }
-
- /*
- * SCANINFO *
- * OpenScanner(char *dev)
- *
- * Description:
- * Get a SCANINFO structure for the scanner connected to dev.
- * This opens the device and does an inquiry to find out what
- * kind of scanner is attached. If it's one we know about, we
- * allocate a SCANINFO structure, fill it in, and return it.
- *
- * Parameters:
- * dev device for the scanner
- *
- * Returns:
- * pointer to a SCANATTRIB if successful, NULL with drverr set if
- * failure.
- */
-
- SCANINFO *
- OpenScanner(char *dev)
- {
- static SCANINFO scan;
- IMPImage *img;
- static SCDATATYPE rgb8types[] = {
- { SC_PACKPLANE, 3, SC_RGB, 8 }, /* planar RGB */
- { SC_PACKPIX, 3, SC_RGB, 8 }, /* pixel packed RGB */
- { SC_PACKPIX, 1, SC_GREY, 8 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_MONO, 1 }, /* 8 black and white */
- };
- static SCDATATYPE rgb16types[] = {
- { SC_PACKPLANE, 3, SC_RGB, 16 }, /* > 8 bit planar RGB */
- { SC_PACKPIX, 3, SC_RGB, 16 }, /* > 8 bit pixel packed RGB */
- { SC_PACKPLANE, 3, SC_RGB, 8 }, /* planar RGB */
- { SC_PACKPIX, 3, SC_RGB, 8 }, /* pixel packed RGB */
- { SC_PACKPIX, 1, SC_GREY, 16 }, /* > 8 bit grey scale */
- { SC_PACKPIX, 1, SC_GREY, 8 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_MONO, 1 }, /* 8 black and white */
- };
- static SCDATATYPE grey8types[] = {
- { SC_PACKPIX, 1, SC_GREY, 8 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_GREY, 8 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_MONO, 1 }, /* 8 black and white */
- };
- static SCDATATYPE grey16types[] = {
- { SC_PACKPIX, 1, SC_GREY, 16 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_GREY, 8 }, /* 8 bit grey scale */
- { SC_PACKPIX, 1, SC_MONO, 1 }, /* 8 black and white */
- };
- static float res = 100; /* set resolution somewhat */
- /* arbitrarily to 100 */
- static char errorBuf[SC_MAXERRSTR];
- char tmpFile[MAXPATHLEN], *tmpDir;
- int bits;
- struct sigaction act, oact;
- pid_t pid;
- int fd, status;
-
- /*
- * Check for file existence before calling impOpen.
- */
- if (access(dev, F_OK | R_OK) != 0) {
- drverr = errno;
- return NULL;
- }
-
- img = impOpen(dev, "r");
-
- /*
- * If the open failed, try using imgcopy to convert the file to
- * SGI format.
- */
- if (!img) {
- drvmsg = impErrorString(IMPerrno);
- drverr = SCEDRVMSG;
-
- /*
- * Create a temp name for use in storing the converted file
- */
- tmpDir = getenv("TMPDIR");
- if (!tmpDir) {
- tmpDir = "/var/tmp";
- }
- (void)sprintf(tmpFile, "%s/fileXXXXXX", tmpDir);
- (void)mktemp(tmpFile);
-
- act.sa_handler = SIG_DFL;
- act.sa_flags = 0;
- (void)sigemptyset(&act.sa_mask);
- (void)sigaction(SIGCHLD, &act, &oact);
-
- pid = fork();
-
- /*
- * Child runs imgcopy
- */
- if (pid == 0) {
- for (fd = getdtablesize(); fd > 2; fd--) {
- (void)close(fd);
- }
- /*
- * Point stderr to /dev/null to get rid of obnoxious error
- * messsages on terminal
- */
- (void)close(2);
- (void)open("/dev/null", O_WRONLY);
- (void)execlp("imgcopy", "imgcopy", "-fSGI", dev, tmpFile, NULL);
- exit(-1);
- }
-
- /*
- * Parent waits for child, and then tries to open the
- * converted file if imgcopy exits with a 0 status
- */
- if (pid > 0) {
- if ((pid = waitpid(pid, &status, 0)) == pid
- && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- img = impOpen(tmpFile, "r");
- }
- }
-
- /*
- * unlink the tmpFile so it doesn't hang around after we're
- * done. We've still got it open, though, and img is our
- * pointer into it.
- */
- (void)unlink(tmpFile);
- (void)sigaction(SIGCHLD, &oact, NULL);
-
- if (!img) {
- return NULL;
- } else {
- /*
- * If we succeeded we have to reset drverr or an error
- * will get reported.
- */
- drverr = 0;
- }
- }
-
- if (impNumChannels(img) < 3 && impNumChannels(img) != 1) {
- (void)sprintf(errorBuf,
- gettxt(_SGI_FILESCAN_BADTYPE,
- "Can't figure out what type of image "
- "file %s is\n"), dev);
- drvmsg = errorBuf;
- drverr = SCEDRVMSG;
- return NULL;
- }
-
- if (impRasterBPP(img) != 1 && impRasterBPP(img) != 2) {
- (void)sprintf(errorBuf,
- gettxt(_SGI_FILESCAN_WEIRDBPP,
- "%s has a weird number of bytes per pixel (%d)"),
- dev, impRasterBPP(img));
- drvmsg = errorBuf;
- drverr = SCEDRVMSG;
- return NULL;
- }
-
- if (impRasterBPP(img) == 2) {
- bits = HowManyBits(impMaxValue(img));
- imgMaxValue = impMaxValue(img);
- imgMinValue = impMinValue(img);
- }
-
- /*
- * If num channels is 3, it's an rgb image. If it's 1, it's a greyscale
- * image. Otherwise, it's a mystery to us.
- */
- if (impNumChannels(img) >= 3) {
- /*
- * The impMaxValue test keeps us out of a situation in which
- * we give bad info to the scan app when we have a strange
- * image file that uses 2 bytes per pixel but doesn't use the
- * high bytes at all.
- */
- if (impRasterBPP(img) == 1 || impMaxValue(img) <= 255) {
- scan.types = rgb8types;
- scan.ntypes = sizeof rgb8types/sizeof *rgb8types;
- } else {
- scan.types = rgb16types;
- scan.ntypes = sizeof rgb16types/sizeof *rgb16types;
- rgb16types[0].bpp = rgb16types[1].bpp = rgb16types[4].bpp = bits;
- }
- } else if (impNumChannels(img) == 1) {
- if (impRasterBPP(img) == 1 || impMaxValue(img) <= 255) {
- scan.types = grey8types;
- scan.ntypes = sizeof grey8types/sizeof *grey8types;
- } else {
- scan.types = grey16types;
- scan.ntypes = sizeof grey16types/sizeof *grey16types;
- grey16types[0].bpp = bits;
- }
- } else {
- drverr = SCENOTSUPPORTED;
- return NULL;
- }
-
- /*
- * This tells main.c that we only support one resolution in
- * "hardware", 100. We set min and max to allow for impulse
- * zooming main.c can do in cooperation with us to achieve other
- * resolutions.
- */
- scan.metric = SC_INCHES;
- scan.nres = 1;
- scan.xres = scan.yres = &res;
-
- scan.minxres = scan.minyres = 1;
- scan.maxxres = scan.maxyres = 2 * res;
-
- scan.pagex = 0;
- scan.pagey = 0;
- scan.pagewidth = impXSize(img) / res;
- scan.pageheight = impYSize(img) / res;
-
- scan.priv = img;
- return &scan;
- }
-
- /*
- * Conversion functions.
- *
- * The following functions convert from the four libimp formats that
- * we support (rgb and greyscale, 1 byte and 2 bytes per pixel) to the
- * seven scanner interface formats that we support (planar rgb 8,
- * planar rgb 16, chunky rgb 8, chunky rgb 16, greyscale 8, greyscale
- * 16, and mono). (If the image file is in greyscale format, we don't
- * convert to color)
- *
- * All conversion takes place in the DoImgProc thread using the
- * "convert" member of the SCANPARAMS structure passed in to
- * SetupScan. In SetupScan we set params->convert to point to the
- * appropriate conversion function given the type of image file we're
- * dealing with and the data type that we've been requested to provide.
- */
-
- /*
- * static void
- * RGB8ToChunky8(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- *
- * Description:
- * Convert a row of banded 8 bit/channel RGB image data to a row
- * of chunky 8 bit/channel RGB image data, cropping as necessary.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 8 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bit/channel chunky RGB data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB8ToChunky8(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- {
- register unsigned char *r, *g, *b;
- register unsigned char *t = tobuf;
- register int x, fx;
-
- /*
- * We're cropping the data as well as converting and zooming it.
- * We skip imgOffset pixels in each channel. imgStride is the
- * number of pixels per channel that we actually read from the
- * image file.
- */
- r = (char *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- /*
- * The zmap test is outside the loops rather than having one loop
- * with the zmap test because we want to reduce the amount of
- * processing per pixel as much as possible.
- */
- if (zmap) {
- for (x = 0; x < tox; x++) {
- fx = zmap[x];
- *t++ = r[fx];
- *t++ = g[fx];
- *t++ = b[fx];
- }
- } else {
- while (tox--) {
- *t++ = *r++;
- *t++ = *g++;
- *t++ = *b++;
- }
- }
- }
-
- /*
- * static void
- * RGB16ToChunky16(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- *
- * Description:
- * Convert a row of banded 16 bit/channel RGB image data to a row
- * of chunky 16 bit/channel RGB image data, cropping as necessary.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 16 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 16 bit/channel chunky RGB data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB16ToChunky16(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- {
- register unsigned short *r, *g, *b;
- register unsigned short *t = tobuf;
- register int x, fx;
-
- /*
- * We're cropping the data as well as converting and zooming it.
- * We skip imgOffset pixels in each channel. imgStride is the
- * number of pixels per channel that we actually read from the
- * image file.
- */
- r = (unsigned short *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- /*
- * The zmap test is outside the loops rather than having one loop
- * with the zmap test because we want to reduce the amount of
- * processing per pixel as much as possible.
- */
- if (zmap) {
- for (x = 0; x < tox; x++) {
- fx = zmap[x];
- *t++ = r[fx];
- *t++ = g[fx];
- *t++ = b[fx];
- }
- } else {
- while (tox--) {
- *t++ = *r++;
- *t++ = *g++;
- *t++ = *b++;
- }
- }
- }
-
- /*
- * static void
- * RGB16ToChunky8(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- *
- * Description:
- * Convert a row of banded 16 bit/channel RGB image data to a row
- * of chunky 8 bit/channel RGB image data, cropping as necessary.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 16 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bit/channel chunky RGB data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB16ToChunky8(void *frombuf, int fromx, void *tobuf, int tox, int *zmap)
- {
- register unsigned short *r, *g, *b;
- register unsigned char *t = tobuf;
- register int x, fx;
-
- /*
- * We're cropping the data as well as converting and zooming it.
- * We skip imgOffset pixels in each channel. imgStride is the
- * number of pixels per channel that we actually read from the
- * image file.
- */
- r = (unsigned short *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- /*
- * The zmap test is outside the loops rather than having one loop
- * with the zmap test because we want to reduce the amount of
- * processing per pixel as much as possible.
- */
- if (zmap) {
- for (x = 0; x < tox; x++) {
- fx = zmap[x];
- *t++ = SCALE(r[fx]);
- *t++ = SCALE(g[fx]);
- *t++ = SCALE(b[fx]);
- }
- } else {
- while (tox--) {
- *t++ = SCALE(*r++);
- *t++ = SCALE(*g++);
- *t++ = SCALE(*b++);
- }
- }
- }
-
- /*
- * static void
- * CropRow8(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- *
- * Description:
- * Crop a row of image data. This function is used when scanning
- * planar RGB from a color image file or when scanning greyscale
- * from a greyscale image file.
- *
- * Parameters:
- * frombuf 8 bits/channel image data
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bits/channel cropped image data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- CropRow8(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- {
- register char *s = (char *)fromBuf + imgOffset;
- register unsigned char *t = toBuf;
- register int x;
-
- if (zmap) {
- for (x = 0; x < tox; x++) {
- *t++ = s[zmap[x]];
- }
- } else {
- while (tox--) {
- *t++ = *s++;
- }
- }
- }
-
- /*
- * static void
- * CropRow16(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- *
- * Description:
- * Crop a row of image data. This function is used when scanning
- * planar RGB from a color image file or when scanning greyscale
- * from a greyscale image file.
- *
- * Parameters:
- * frombuf 16 bits/channel image data
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 16 bits/channel cropped image data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- CropRow16(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- {
- register unsigned short *s = (unsigned short *)fromBuf + imgOffset;
- register unsigned short *t = toBuf;
- register int x;
-
- if (zmap) {
- for (x = 0; x < tox; x++) {
- *t++ = s[zmap[x]];
- }
- } else {
- while (tox--) {
- *t++ = *s++;
- }
- }
- }
-
- /*
- * static void
- * CropRow16To8(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- *
- * Description:
- * Crop a row of image data. This function is used when scanning
- * planar RGB from a color image file or when scanning greyscale
- * from a greyscale image file.
- *
- * Parameters:
- * frombuf 16 bits/channel image data
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bits/channel cropped image data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- CropRow16To8(void *fromBuf, int fromx, void *toBuf, int tox, int *zmap)
- {
- register unsigned short *s = (unsigned short *)fromBuf + imgOffset;
- register unsigned char *t = toBuf;
- register int x;
-
- if (zmap) {
- for (x = 0; x < tox; x++) {
- *t++ = SCALE(s[zmap[x]]);
- }
- } else {
- while (tox--) {
- *t++ = SCALE(*s++);
- }
- }
- }
-
- /*
- * static void
- * RGB8ToGrey8(void *frombuf, int fromx, void *tobuf,
- * register int tox, int *zmap)
- *
- * Description:
- * Convert a row of RGB banded data to greyscale. This involves
- * adding together the illumination contributions of each of the
- * red, green, and blue channels of information.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 8 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bit greyscale data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB8ToGrey8(void *frombuf, int fromx, void *tobuf,
- register int tox, int *zmap)
- {
- register char *r, *g, *b;
- register unsigned char *t = tobuf;
- register int z;
-
- r = (char *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- if (zmap) {
- while (tox--) {
- z = *zmap++;
- *t++ = ILUM(r[z], g[z], b[z]);
- }
- } else {
- while (tox--) {
- *t++ = ILUM(*r++, *g++, *b++);
- }
- }
- }
-
- /*
- * static void
- * RGB16ToGrey16(void *frombuf, int fromx, void *tobuf,
- * register int tox, int *zmap)
- *
- * Description:
- * Convert a row of RGB banded data to greyscale. This involves
- * adding together the illumination contributions of each of the
- * red, green, and blue channels of information.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 16 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 16 bit greyscale data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB16ToGrey16(void *frombuf, int fromx, void *tobuf,
- register int tox, int *zmap)
- {
- register unsigned short *r, *g, *b;
- register unsigned short *t = tobuf;
- register int z;
-
- r = (unsigned short *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- if (zmap) {
- while (tox--) {
- z = *zmap++;
- *t++ = ILUM(r[z], g[z], b[z]);
- }
- } else {
- while (tox--) {
- *t++ = ILUM(*r++, *g++, *b++);
- }
- }
- }
-
- /*
- * static void
- * RGB16ToGrey8(void *frombuf, int fromx, void *tobuf,
- * register int tox, int *zmap)
- *
- * Description:
- * Convert a row of RGB banded data to greyscale. This involves
- * adding together the illumination contributions of each of the
- * red, green, and blue channels of information.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 16 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 8 bit greyscale data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- /*ARGSUSED*/
- static void
- RGB16ToGrey8(void *frombuf, int fromx, void *tobuf,
- register int tox, int *zmap)
- {
- register unsigned short *r, *g, *b;
- register unsigned char *t = tobuf;
- register int z;
-
- r = (unsigned short *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- if (zmap) {
- while (tox--) {
- z = *zmap++;
- *t++ = SCALE(ILUM(r[z], g[z], b[z]));
- }
- } else {
- while (tox--) {
- *t++ = SCALE(ILUM(*r++, *g++, *b++));
- }
- }
- }
-
- /*
- * static void
- * ScaleRow(void *from, void *to, register int width)
- *
- * Description:
- * Scale row is used by functions that convert from 2 byte per
- * pixel data to 1 byte per pixel data. First, the data is
- * scaled, and then the appropriate conversion takes place.
- *
- * Parameters:
- * from source row
- * to destination row
- * width width of row in pixels
- */
-
- static void
- ScaleRow(void *from, void *to, register int width)
- {
- register unsigned char *c = (unsigned char *)to + imgOffset;
- register unsigned short *s = (unsigned short *)from + imgOffset;
-
- while (width--) {
- *c++ = SCALE(*s++);
- }
- }
-
- /*
- * static void
- * ScaleRowRGB(void *from, void *to, int width)
- *
- * Description:
- * Scale row is used by functions that convert from 2 byte per
- * pixel data to 1 byte per pixel data. First, the data is
- * scaled, and then the appropriate conversion takes place.
- *
- * Parameters:
- * from source row
- * to destination row
- * width width of row in pixels
- */
-
- static void
- ScaleRowRGB(void *from, void *to,int width)
- {
- register unsigned char *c = (unsigned char *)to + imgOffset;
- register unsigned short *s = (unsigned short *)from + imgOffset;
- register int x = width;
-
- while (x--) {
- *c++ = SCALE(*s++);
- }
-
- x = width;
- c += imgStride - width;
- s += imgStride - width;
-
- while (x--) {
- *c++ = SCALE(*s++);
- }
-
- x = width;
- c += imgStride - width;
- s += imgStride - width;
-
- while (x--) {
- *c++ = SCALE(*s++);
- }
- }
-
- /*
- * static void
- * RGB8ToMono(void *frombuf, int fromx,
- * void *tobuf, register int tox, int *zmap)
- *
- * Description:
- * Convert a row of RGB banded data to monochrome by calculating
- * the illumination contributions of each channel and then
- * thresholding the result.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 8 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 1 bit monochrome data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- static void
- RGB8ToMono(void *frombuf, int fromx, void *tobuf, register int tox, int *zmap)
- {
- register char *r, *g, *b;
- register unsigned char *t = tobuf;
- int x, endx, shift;
-
- r = (char *)frombuf + imgOffset;
- g = r + imgStride;
- b = g + imgStride;
-
- if (fromx == tox) {
- while (tox >= 8) {
- *t++ = THRESH(ILUM(r[0], g[0], b[0]), THRESHVAL) << 7 |
- THRESH(ILUM(r[1], g[1], b[1]), THRESHVAL) << 6 |
- THRESH(ILUM(r[2], g[2], b[2]), THRESHVAL) << 5 |
- THRESH(ILUM(r[3], g[3], b[3]), THRESHVAL) << 4 |
- THRESH(ILUM(r[4], g[4], b[4]), THRESHVAL) << 3 |
- THRESH(ILUM(r[5], g[5], b[5]), THRESHVAL) << 2 |
- THRESH(ILUM(r[6], g[6], b[6]), THRESHVAL) << 1 |
- THRESH(ILUM(r[7], g[7], b[7]), THRESHVAL);
- tox -= 8;
- r += 8;
- g += 8;
- b += 8;
- }
-
- *t = 0;
- while (tox--) {
- *t |= THRESH(ILUM(r[tox], g[tox], b[tox]), THRESHVAL) << (7 - tox);
- }
- } else {
- register int x0, x1, x2, x3, x4, x5, x6, x7;
- int endx = tox & ~7;
- for (x = 0; x < endx; x += 8) {
- x0 = zmap[x];
- x1 = zmap[x + 1];
- x2 = zmap[x + 2];
- x3 = zmap[x + 3];
- x4 = zmap[x + 4];
- x5 = zmap[x + 5];
- x6 = zmap[x + 6];
- x7 = zmap[x + 7];
- *t++ = THRESH(ILUM(r[x0], g[x0], b[x0]), THRESHVAL) << 7 |
- THRESH(ILUM(r[x1], g[x1], b[x1]), THRESHVAL) << 6 |
- THRESH(ILUM(r[x2], g[x2], b[x2]), THRESHVAL) << 5 |
- THRESH(ILUM(r[x3], g[x3], b[x3]), THRESHVAL) << 4 |
- THRESH(ILUM(r[x4], g[x4], b[x4]), THRESHVAL) << 3 |
- THRESH(ILUM(r[x5], g[x5], b[x5]), THRESHVAL) << 2 |
- THRESH(ILUM(r[x6], g[x6], b[x6]), THRESHVAL) << 1 |
- THRESH(ILUM(r[x7], g[x7], b[x7]), THRESHVAL);
- }
-
- shift = 7;
- *t = 0;
- while (x < tox) {
- *t |= THRESH(ILUM(r[zmap[x]], g[zmap[x]], b[zmap[x]]),
- THRESHVAL) << shift;
- x++;
- shift--;
- }
- }
- }
-
- /*
- * static void
- * RGB16ToMono(void *frombuf, int fromx,
- * void *tobuf, register int tox, int *zmap)
- *
- * Description:
- * Convert a row of RGB banded data to monochrome by calculating
- * the illumination contributions of each channel and then
- * thresholding the result.
- *
- * Parameters:
- * frombuf Banded RGB data from image file, 16 bits/pixel/channel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 1 bit monochrome data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- static void
- RGB16ToMono(void *frombuf, int fromx, void *tobuf, register int tox, int *zmap)
- {
- ScaleRowRGB(frombuf, imgTempBuf, fromx);
- RGB8ToMono(imgTempBuf, fromx, tobuf, tox, zmap);
- }
-
- /*
- * static void
- * Grey8ToMono(void *frombuf, int fromx,
- * void *tobuf, register int tox, int *zmap)
- *
- * Description:
- * Convert a row of 8 bit/pixel grey scale to a row of 1
- * bit/pixel monochrome data, cropping and zooming as necessary.
- *
- * Parameters:
- * frombuf Greyscale image data, 8 bits/pixel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 1 bit monochrome data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- static void
- Grey8ToMono(void *frombuf, int fromx, void *tobuf, register int tox, int *zmap)
- {
- char *f = (char *)frombuf + imgOffset;
- unsigned char *t = tobuf;
- int x, endx, shift;
-
- if (fromx == tox) {
- while (tox >= 8) {
- *t++ = THRESH(f[0], THRESHVAL) << 7 |
- THRESH(f[1], THRESHVAL) << 6 |
- THRESH(f[2], THRESHVAL) << 5 |
- THRESH(f[3], THRESHVAL) << 4 |
- THRESH(f[4], THRESHVAL) << 3 |
- THRESH(f[5], THRESHVAL) << 2 |
- THRESH(f[6], THRESHVAL) << 1 |
- THRESH(f[7], THRESHVAL);
- tox -= 8;
- f += 8;
- }
-
- *t = 0;
- while (tox--) {
- *t |= THRESH(f[tox], THRESHVAL) << (7 - tox);
- }
- } else {
- endx = tox & ~7;
- for (x = 0; x < endx; x += 8) {
- *t++ = THRESH(f[zmap[x]], THRESHVAL) << 7 |
- THRESH(f[zmap[x + 1]], THRESHVAL) << 6 |
- THRESH(f[zmap[x + 2]], THRESHVAL) << 5 |
- THRESH(f[zmap[x + 3]], THRESHVAL) << 4 |
- THRESH(f[zmap[x + 4]], THRESHVAL) << 3 |
- THRESH(f[zmap[x + 5]], THRESHVAL) << 2 |
- THRESH(f[zmap[x + 6]], THRESHVAL) << 1 |
- THRESH(f[zmap[x + 7]], THRESHVAL);
- }
-
- shift = 7;
- *t = 0;
- while (x < tox) {
- *t |= THRESH(f[zmap[x]], THRESHVAL) << shift;
- shift--;
- x++;
- }
- }
- }
-
- /*
- * static void
- * Grey16ToMono(void *frombuf, int fromx,
- * void *tobuf, register int tox, int *zmap)
- *
- * Description:
- * Convert a row of 16 bit/pixel grey scale to a row of 1
- * bit/pixel monochrome data, cropping and zooming as necessary.
- *
- * Parameters:
- * frombuf Greyscale image data, 16 bits/pixel
- * fromx In theory, the width of fromx. In actuality,
- * imgStride is the width of frombuf and fromx is what
- * we set params->xpixels to in SetupScan to make the
- * main.c module set up zmap right if we're zooming.
- * tobuf 1 bit monochrome data
- * tox width of tox
- * zmap Zoom map for impulse zoom
- */
-
- static void
- Grey16ToMono(void *frombuf, int fromx,
- void *tobuf, register int tox, int *zmap)
- {
- ScaleRow(frombuf, imgTempBuf, fromx);
- Grey8ToMono(imgTempBuf, fromx, tobuf, tox, zmap);
- }
-
- /*
- * Functions for reading the data from the image file.
- *
- * These four functions convert from the coordinate system used by the
- * scanner interface, which has the origin in the upper left corner of
- * the image area, to the coordinate system that libimage uses, which
- * has the origin in the lower left corner of the image area.
- */
-
- /*
- * static int
- * DoGetRows(IMPImage *img, short y, short z, void *buf, int nrows)
- *
- * Description:
- * Get rows of image data from an SGI image file. Used for
- * reading from greyscale files and also from rgb files if we're
- * converting to planar.
- *
- * Parameters:
- * img SGI image file pointer
- * y y coordinate (in scanner interface coordinates)
- * z z coordinage (0 == red or grey, 1 == green, 2 == blue)
- * buf Buffer that the data will be read into
- * nrows The number of rows to read (currently must be 1)
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- /*ARGSUSED*/
- static int
- DoGetRows(IMPImage *img, short y, short z, void *buf, int nrows)
- {
- short imgy;
-
- imgy = impYSize(img) - y - 1;
- if (impReadRowB(img, buf, imgy, z) == -1) {
- return -1;
- }
- return 0;
- }
-
- /*
- * static int
- * DoGetRows16(IMPImage *img, short y, short z, void *buf, int nrows)
- *
- * Description:
- * Get rows of image data from an SGI image file. Used for
- * reading from greyscale files and also from rgb files if we're
- * converting to planar.
- *
- * Parameters:
- * img SGI image file pointer
- * y y coordinate (in scanner interface coordinates)
- * z z coordinage (0 == red or grey, 1 == green, 2 == blue)
- * buf Buffer that the data will be read into
- * nrows The number of rows to read (currently must be 1)
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- /*ARGSUSED*/
- static int
- DoGetRows16(IMPImage *img, short y, short z, void *buf, int nrows)
- {
- short imgy;
-
- imgy = impYSize(img) - y - 1;
- if (impReadRow(img, buf, imgy, z) == -1) {
- return -1;
- }
- return 0;
- }
-
- /*
- * static int
- * DoGetRowsRGB(IMPImage *img, short y, short z, void *buf, int nrows)
- *
- * Description:
- * Get rows of image data from an SGI rgb image file. This is
- * used for reading from rgb files if we're converting to rgb
- * chunky, greyscale, or monochrome. We use DoGetRows for rgb
- * planar.
- *
- * Parameters:
- * img SGI image file pointer
- * y y coordinate (in scanner interface coordinates)
- * z ignored in this function
- * buf Buffer that the data will be read into
- * nrows The number of rows to read (currently must be 1)
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- /*ARGSUSED*/
- static int
- DoGetRowsRGB(IMPImage *img, short y, short z, void *buf, int nrows)
- {
- short imgy;
- unsigned char *b = buf;
-
- imgy = impYSize(img) - y - 1;
-
- if (impReadRowB(img, b, imgy, 0) == -1) { /* red */
- return -1;
- }
-
- b += impXSize(img);
- if (impReadRowB(img, b, imgy, 1) == -1) { /* green */
- return -1;
- }
-
- b += impXSize(img);
- if (impReadRowB(img, b, imgy, 2) == -1) { /* blue */
- return -1;
- }
-
- return 0;
- }
-
- /*
- * static int
- * DoGetRowsRGB16(IMPImage *img, short y, short z, void *buf, int nrows)
- *
- * Description:
- * Get rows of image data from an SGI rgb image file. This is
- * used for reading from rgb files if we're converting to rgb
- * chunky, greyscale, or monochrome. We use DoGetRows for rgb
- * planar.
- *
- * Parameters:
- * img SGI image file pointer
- * y y coordinate (in scanner interface coordinates)
- * z ignored in this function
- * buf Buffer that the data will be read into
- * nrows The number of rows to read (currently must be 1)
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- /*ARGSUSED*/
- static int
- DoGetRowsRGB16(IMPImage *img, short y, short z, void *buf, int nrows)
- {
- short imgy;
- short *b = buf;
-
- imgy = impYSize(img) - y - 1;
-
- if (impReadRow(img, b, imgy, 0) == -1) { /* red */
- return -1;
- }
-
- b += impXSize(img);
- if (impReadRow(img, b, imgy, 1) == -1) { /* green */
- return -1;
- }
-
- b += impXSize(img);
- if (impReadRow(img, b, imgy, 2) == -1) { /* blue */
- return -1;
- }
-
- return 0;
- }
-
- /*
- * int
- * SetupScan(SCANPARAMS *params)
- *
- * Description:
- * Get ready to perform a scan. params is a value result
- * parameter; it has fields that describe the scanning parameters
- * desired by the scanning application, and fields that this
- * function is responsible for setting.
- *
- * Parameters:
- * params scanning parameters (in/out)
- *
- * Returns:
- * 0 if successful, -1 with drverr set if error
- */
-
- int
- SetupScan(SCANPARAMS *params)
- {
- IMPImage *img = params->s->priv;
-
- /*
- * xres and yres will always be 100, because we told main.c that
- * that is the only resolution we can do in "hardware". main.c
- * will set up a zoom map for us later if any zooming needs to
- * occur.
- */
- params->xpixels = params->width * params->xres;
- params->ylines = params->height * params->yres;
-
- if (impRasterBPP(img) == 1) {
- if (impNumChannels(img) >= 3) {
- /*
- * Set xbytes, convert, and imgGetRows appropriately for rgb
- * image files.
- */
- switch (params->type.type) {
- case SC_RGB:
- if (params->type.packing == SC_PACKPLANE) {
- params->xbytes = impXSize(img);
- params->convert = CropRow8;
- imgGetRows = DoGetRows;
- } else {
- params->xbytes = impXSize(img) * 3;
- params->convert = RGB8ToChunky8;
- imgGetRows = DoGetRowsRGB;
- }
- break;
- case SC_GREY:
- params->xbytes = impXSize(img) * 3;
- params->convert = RGB8ToGrey8;
- imgGetRows = DoGetRowsRGB;
- break;
- case SC_MONO:
- params->xbytes = impXSize(img) * 3;
- params->convert = RGB8ToMono;
- imgGetRows = DoGetRowsRGB;
- break;
- default:
- drverr = SCEBADTYPE;
- return -1;
- }
- } else {
- /*
- * Set xbytes, convert, and imgGetRows appropriately for
- * greyscale image files.
- */
- params->xbytes = impXSize(img);
- params->convert = params->type.type == SC_GREY ?
- CropRow8 : Grey8ToMono;
- imgGetRows = DoGetRows;
- }
- } else {
- if (impNumChannels(img) >= 3) {
- switch (params->type.type) {
- case SC_RGB:
- if (params->type.packing == SC_PACKPLANE) {
- params->xbytes = impXSize(img) * sizeof (unsigned short);
- imgGetRows = DoGetRows16;
- params->convert = params->type.bpp > 8 ?
- CropRow16 : CropRow16To8;
- } else {
- params->xbytes =
- impXSize(img) * 3 * sizeof (unsigned short);
- imgGetRows = DoGetRowsRGB16;
- params->convert = params->type.bpp > 8 ?
- RGB16ToChunky16 : RGB16ToChunky8;
- }
- break;
- case SC_GREY:
- params->xbytes = impXSize(img) * 3 * sizeof (unsigned short);
- imgGetRows = DoGetRowsRGB16;
- params->convert = params->type.bpp > 8 ?
- RGB16ToGrey16 : RGB16ToGrey8;
- break;
- case SC_MONO:
- params->xbytes = impXSize(img) * 3 * sizeof (unsigned short);
- imgGetRows = DoGetRowsRGB16;
- params->convert = RGB16ToMono;
- if (imgTempBuf) {
- free(imgTempBuf);
- }
- imgTempBuf = malloc(impXSize(img) * 3);
- break;
- }
- } else {
- params->xbytes = impXSize(img) * sizeof (unsigned short);
- imgGetRows = DoGetRows16;
- if (params->type.type == SC_GREY) {
- params->convert = params->type.bpp > 8 ?
- CropRow16 : CropRow16To8;
- } else {
- params->convert = Grey16ToMono;
- if (imgTempBuf) {
- free(imgTempBuf);
- }
- imgTempBuf = malloc(impXSize(img));
- }
- }
- }
-
-
- /*
- * Set readlines = 1 because at this point that's the only number
- * of lines that DoGetRows and DoGetRowsRGB supports. If those
- * two functions were expanded to do more, than this could be set
- * higher and everything should work (DoScan already does the
- * right thing).
- */
- params->readlines = 1;
- imgOffset = params->x * params->xres;
- imgStride = impXSize(img);
- return 0;
- }
-
- /*
- * int
- * ScanReset(SCANINFO *scan)
- *
- * Description:
- * Reset the scanner to its ready state. This is called after a
- * scan has been aborted. We don't have to do anything here.
- *
- * Parameters:
- * scan Describes the scanner to reset
- *
- * Returns:
- * 0 if successful, -1 with drverr set if error
- */
-
- /*ARGSUSED*/
- int
- ScanReset(SCANINFO *scan)
- {
- return 0;
- }
-
- /*
- * void
- * DoScan(SCANPARAMS *params)
- *
- * Description:
- * Perform a scan. We read the data from the scanner and put it on the
- * scan queue so that the image processing process can get it. This
- * function exits when it's done; it's meant to be called via sproc().
- *
- * Parameters:
- * params parameters for the scan
- */
-
- void
- DoScan(SCANPARAMS *params)
- {
- SCANINFO *s = params->s;
- IMPImage *img = s->priv;
- void *buf;
- int toread, curline;
- int imgy, y, z;
- int npasses;
-
- /*
- * Exit if our parent dies
- */
- prctl(PR_TERMCHILD);
-
- y = params->y * params->yres;
-
- npasses = params->type.type == SC_RGB &&
- params->type.packing == SC_PACKPLANE ? 3 : 1;
-
- for (z = 0; z < npasses; z++) {
- for (curline = 0; curline < params->ylines;
- curline += params->readlines) {
- toread = MIN(params->readlines,
- params->ylines - curline);
-
- imgy = y + curline;
- buf = SCDequeue(params->sfreeq);
-
- /*
- * Get the scan data here!
- */
- if ((*imgGetRows)(img, imgy, z, buf, params->readlines) < 0) {
- drverr = SCEDRVMSG;
- drvmsg = impErrorString(IMPerrno);
- exit(1);
- }
-
- /*
- * Chop the buffer up into scan line sized chunks
- */
- while (toread--) {
- SCEnqueue(params->scanq, buf);
- buf = (char *)buf + params->xbytes;
- }
- }
- }
-
- exit(0);
- }
-
- /*
- * These feeder functions should never get called, since we have
- * denied having a feeder by not setting the feederFlags member of the
- * SCANINFO struct in OpenScanner. See the scanner driver template
- * version of scan.c for comments on what these functions should do if
- * there really is a feeder attached.
- */
-
- /*ARGSUSED*/
- int
- SetFeederFlags(SCANINFO *scan, SCFEEDERFLAGS flags)
- {
- drverr = SCENOFEEDER;
- return -1;
- }
-
- /*ARGSUSED*/
- int
- AdvanceFeeder(SCANINFO *scan)
- {
- drverr = SCENOFEEDER;
- return -1;
- }
-
- /*ARGSUSED*/
- int
- FeederReady(SCANINFO *scan)
- {
- drverr = SCENOFEEDER;
- return -1;
- }
-
- /*
- * void
- * PrintID(FILE *fp)
- *
- * Description:
- * Print a string to fp that describes the type of scanner that
- * this driver supports.
- *
- * Parameters:
- * fp stream upon which to print scanner id string
- */
-
- void
- PrintID(FILE *fp)
- {
- fprintf(fp, "SGI Image File\n"); /* String describing scanner */
- fprintf(fp, "Other"); /* Device type; can be list */
- }
-
- /*
- * void
- * FindScanners(FILE *fp)
- *
- * Description:
- * Look for scanners that this driver can support. Since this
- * isn't really feasible for SGI image files, we just print
- * nothing.
- *
- * Parameters:
- * fp stream upon which to print stuff
- */
-
- /*ARGSUSED*/
- void
- FindScanners(FILE *fp)
- {
- }
-
- /*
- * int
- * InstallScanner(char *dev)
- *
- * Description:
- * This function gets called to implement the "-install" option
- * of the driver. The scanner installation tool wants to install
- * a scanner with us as the driver and dev as the device.
- *
- * In our case, "dev" is supposedly an image file. We make sure
- * that we can read it, that iopen can open it, and that it's an
- * image file that we understand.
- *
- * Parameters:
- * dev Device to use to install scanner
- *
- * Returns:
- * 0 if successful, -1 if error.
- */
-
- int
- InstallScanner(char *dev)
- {
- IMPImage *img;
- SCANINFO *scan;
-
- if (access(dev, F_OK | R_OK) != 0) {
- printf(gettxt(_SGI_FILESCAN_CANTACCESS,
- "Can't open %s for reading: %s\n"),
- dev, strerror(errno));
- return -1;
- }
-
- scan = OpenScanner(dev);
-
- if (!scan) {
- printf("%s\n", drverr == SCEDRVMSG ? drvmsg : SCErrorString(drverr));
- }
-
- return 0;
- }
-
- /*
- * int
- * DeleteScanner(char *dev)
- *
- * Description:
- * This function gives the scanner driver the opportunity to
- * deallocate any resources allocated during InstallScanner, and
- * to do any scanner-specific cleanup necessary for deleting a
- * scanner.
- *
- * Parameters:
- * dev Device of scanner being deleted
- *
- * Returns:
- * 0 if successful, -1 if error.
- */
-
- /*ARGSUSED*/
- int
- DeleteScanner(char *dev)
- {
- return 0;
- }
-
- /*
- * void *
- * GetSaveOptions(SCANINFO *scan, int *nBytes)
- *
- * Description:
- * This function should return to the main.c module a pointer to
- * some bytes representing our current settings that we got from
- * our scanner specific options program. If we don't have a
- * scanner specific options program, we just set drverr and
- * return NULL.
- *
- * The reason for doing this is so that the scanner application
- * can save some state for us, and at a later time give us the
- * same bytes back so that we can make our state match what it
- * was before.
- *
- * Parameters:
- * scan SCANINFO
- * nBytes we fill this in with the number of bytes we're returning
- *
- * Returns:
- * pointer to bytes containing scanner specific options settings
- * if successful, NULL if error. drverr must be set to an
- * appropriate error code from <scanner.h> or <sys/errno.h> if an
- * error occurs.
- */
-
- void *
- GetSaveOptions(SCANINFO *scan, int *nBytes)
- {
- drverr = SCENOSAVEOPT;
- return NULL;
- }
-
- /*
- * int
- * SetSaveOptions(SCANINFO *scan, void *options, int nBytes)
- *
- * Description:
- * In this function, the scanner application is restoring state
- * that it previously saved after calling GetSaveOptions. We
- * should reset our state to reflect the options passed to us.
- *
- * These are scanner specific settings that were set by our
- * scanner specific options program; we don't need to worry about
- * things like resolution and scanning area and data type that
- * are a part of the standard scanning protocol here.
- *
- * Parameters:
- * scan SCANINFO
- * options the saved settings
- * nBytes number of bytes pointed to by options
- *
- * Returns:
- * 0 if successful, -1 if error. drverr must be set to an
- * appropriate error code from <scanner.h> or <sys/errno.h> if an
- * error occurs.
- */
-
- int
- SetSaveOptions(SCANINFO *scan, void *options, int nBytes)
- {
- drverr = SCENOSAVEOPT;
- return -1;
- }
-